#pragma once

class PlayerContainer;
class Communicator;
class Player;
class Camera;
class PlayerCamera;
class Terrain;
class PostProcessFog;
class PostProcessSSAO;
class TerrainEditor;
class CLManager;
class ParticleSystem;
class Avatar;
class GenerateNormalMap;
class ParticleEffect;

class GameManager
{
public:
	static GameManager* getInstance();

    void init(const glm::ivec2& _windowDim, bool isServer);
	virtual ~GameManager();
	void Tick(float dt);
    void shootParticles();
    
	void toggleFlushError() { flushError = !flushError; (flushError) ? printf("Flusing GLError") : printf("Stopped Flusing GLError"); }
	void toggleVSync() { vSync = !vSync; vSync ? glfwSwapInterval(1) : glfwSwapInterval(0); }
    void toggleWire() { wire = !wire; }
    void toggleFPS() { showFPS = !showFPS; }

    Avatar* getLocalAvatar();
    Player* getLocalPlayer();

    /* decide on where to stuff the objects: 
    Alternatives:
        1. stuff all local objects in one vector
           stuff all external objects in another vector 
        2. store GO's in a map<gameclientID, obj> 
        3. 

        * How do we handle external objects? Never update locally? we obviously need to spawn particle locally f.ex 
    */ 

    Camera*         activeCamera;
    /*Avatar*         localPlayer;*/
    PlayerContainer* playerContainer;
    Terrain*        terrain;
    TerrainEditor*  ted;
    CLManager*      clManager;
    ParticleSystem* particleSystem;
    bool running;
    bool showFPS;
    bool wire;
    bool flushError;
    bool vSync;
    glm::ivec2 windowDim;

private:
	static GameManager* instance;

	GameManager();
	void update(float dt);
	void render(float dt);
	void initMainFBO(); 

    float elapsedFPS;
    unsigned int frameCounter;

	Texture sceneColorTex;
	Texture sceneDepthTex;
	Texture sceneNormalTex;
	Texture scenePositionTex;
	Texture scenePickingTex;
	GLuint sceneFBO;

	PostProcessFog* ppFog;
	PostProcessSSAO* ppSSAO;
    GenerateNormalMap* normGen;

    std::vector<ParticleEffect*> effectList;
    std::map<int, Player> gameClients;
    Communicator* communicator;
};


